﻿#include "CameraFactory.h"
#include <QCameraInfo>
#include "CameraPC.h"
#include "../CameraHikVision/CameraHikVision.h"
#include "../CameraOpenCV/OpenCVDshowCamera.h"
#include "../CameraToupCam/CameraToupCam.h"
#include "../CameraImagingSource/CameraTis.h"
//#include "../CameraBasler/BaslerCamera.h"

namespace Qly{

CameraFactory::CameraFactory()
{

}

IndustryCamera * CameraFactory::defaultCamera(QList<CameraType> type, QObject *parent)
{
    IndustryCamera * pCamera = nullptr;
    QListIterator<CameraType> i(type);
    while(i.hasNext())
    {
        pCamera = defaultCamera(i.next(), parent);
        if(pCamera) break;
    }
    qDebug() << "CameraFactory::defaultCamera, " << pCamera;
    return pCamera;
}

IndustryCamera * CameraFactory::findCameraByName(QString name, QObject *parent)
{
    IndustryCamera * camera = nullptr;

    camera = findCameraHikVisionCamera(name, parent);
    if(camera)
    {
        return camera;
    }
//    camera = findCameraTisByName(name);
//    if(camera)
//    {
//        return camera;
//    }
//    camera = findCameraToupCamByName(name);
//    if(camera)
//    {
//        return camera;
//    }
    camera = findCameraPCByName(name, parent);
    if(camera)
    {
        return camera;
    }
    return camera;
}

Qly::CameraHikVision * CameraFactory::findCameraHikVisionCamera(QString name, QObject *parent)
{
    Qly::CameraHikVision * camera = new Qly::CameraHikVision(parent);
    if(!camera->openCameraByID(name))
    {
        delete camera;
        camera = nullptr;
    }
    return camera;
}

//CameraToupCam * CameraFactory::findCameraToupCamByName(QString name, QObject *parent)
//{
//    CameraToupCam * camera = nullptr;
//    camera = new CameraToupCam(parent);
//    if(!camera->openCameraByID(name))
//    {
//        delete camera;
//        camera = nullptr;
//    }
//    return camera;
//}

//BaslerGigECamera * CameraFactory::findBaslerGigECameraByName(QString name)
//{
//    BaslerGigECamera * camera = nullptr;
//    QList<BaslerCameraInfo> cameras =  BaslerCameraInfo::availableCameras();
//    for (const BaslerCameraInfo &cameraInfo : cameras)
//    {
//        if (cameraInfo.deviceName() == name)
//        {
//            camera = new BaslerGigECamera;
//            camera->open(cameraInfo);
//        }
//    }
//    return camera;
//}

//CameraTis * CameraFactory::findCameraTisByName(QString name, QObject *parent)
//{
//    CameraTis * camera = nullptr;
//    TisCameraInfo info(name);
//    if(!info.isNull())
//    {
//        camera = new CameraTis(parent);
//        camera->openDevice(info);
//    }
//    return camera;
//}

//OpenCVDShowCamera *CameraFactory::findOpenCVDShowCamera(QString name, QObject *parent)
//{
//    OpenCVDShowCamera * pCamera = nullptr;
//    pCamera = new OpenCVDShowCamera(parent);
//    if( pCamera->openCameraByName(name) )
//    {
//        return pCamera;
//    }
//    else
//    {
//        pCamera->close();
//        delete pCamera;
//    }
//    return nullptr;
//}

PCCamera * CameraFactory::findCameraPCByName(QString name, QObject *parent)
{
    PCCamera * camera = nullptr;
    const QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
    for (const QCameraInfo &cameraInfo : cameras)
    {
        if (cameraInfo.deviceName() == name)
        {
            camera = new PCCamera(parent);
            camera->openCameraByInfo(cameraInfo);
        }
    }
      return camera;
}

IndustryCamera * CameraFactory::defaultCamera(CameraType type, QObject *parent)
{
    IndustryCamera * pCamera = nullptr;

    switch (type) {
//    case OPENCV_DSHOW:
//        pCamera = defaultOpenCVDShowCamera(parent);
//        qDebug() << "defaultOpenCVDShowCamera(parent) = " << pCamera;
//        break;
    case HIK_GIGE:
        pCamera = defaultHikCamera(HIK_GIGE, parent);
        qDebug() << "defaultHikCamera(HIK_GIGE) = " << pCamera;
        break;
//    case TIS_GIGE:
//        pCamera = defaultTisCamera(parent);
//        qDebug() << "defaultTisCamera(HIK_GIGE) = " << pCamera;
//        break;
    case BASLER_GIGE:
//        pCamera = defaultBaslerGigECamera(parent);
        qDebug() << "defaultBaslerGigECamera() = " << pCamera;
        break;
    case HIK_USB:
        pCamera = defaultHikCamera(HIK_USB, parent);
        qDebug() << "defaultHikCamera(HIK_USB) = " << pCamera;
        break;
//    case TOUP_USB:
//        pCamera = defaultToupCam(parent);
//        qDebug() << "defaultToupCam() = " << pCamera;
//        break;
    case SYS_CAM:
        pCamera = defaultPCCamera(parent);
        qDebug() << "defaultPCCamera() = " << pCamera;
        break;
    }
    return pCamera;
}

//BaslerGigECamera * CameraFactory::defaultBaslerGigECamera()
//{
//    BaslerGigECamera * camera = new BaslerGigECamera(nullptr);
//    if( camera->openDefaultCamera())
//    {
//        return camera;
//    }
//    delete camera;
//    return nullptr;
//}

//CameraTis * CameraFactory::defaultTisCamera(QObject *parent)
//{
//    TisCameraInfo info = Qly::TisCameraInfo::defaultCamera();
//    if(info.isNull())
//    {
//        return nullptr;
//    }
//    CameraTis *camera = new Qly::CameraTis(parent);
//    if(camera->openDefaultCamera())
//    {
//        return camera;
//    }
//    else
//    {
//        delete camera;
//    }

//    return nullptr;

//}

//OpenCVDShowCamera * CameraFactory::defaultOpenCVDShowCamera(QObject *parent)
//{
//    OpenCVDShowCamera * camera = new OpenCVDShowCamera(parent);
//    camera->openDefaultCamera();
//    return camera;
//}

PCCamera * CameraFactory::defaultPCCamera(QObject *parent)
{
    QCameraInfo info = QCameraInfo::defaultCamera();
    if(info.isNull()) return nullptr;
    PCCamera * c = new PCCamera(parent);
    c->openDefaultCamera();

    return c;
}

//CameraToupCam * CameraFactory::defaultToupCam(QObject *parent)
//{
//    CameraToupCam * camera = new CameraToupCam(parent);
//    if( camera->openByIdx(0) )
//    {
//        return camera;
//    }
//    delete camera;
//    return nullptr;
//}

Qly::CameraHikVision * CameraFactory::defaultHikCamera(CameraType type, QObject *parent)
{
    unsigned int nTLayerType;
    if( (type & HIK_GIGE) && (type & HIK_USB) )
    {
        nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;
    }
    else if(type & HIK_GIGE)
    {
        nTLayerType = MV_GIGE_DEVICE;
    }
    else if(type & HIK_USB)
    {
        nTLayerType = MV_USB_DEVICE;
    }
    else
    {
        return nullptr;
    }
    MV_CC_DEVICE_INFO_LIST stDevList = {0};
    int nRet = MV_CC_EnumDevices(nTLayerType, &stDevList);
    if (MV_OK != nRet)
        {
            qWarning("error: MV_CC_EnumDevices fail [%x]", nRet);
            return nullptr;
        }
        if (stDevList.nDeviceNum == 0)
        {
            qWarning("no hikvision camera found!");
            return nullptr;
        }
    //选择查找到的第一台在线设备，创建设备句柄
    int nDeviceIndex = 0;
    MV_CC_DEVICE_INFO stDevInfo = {0};
    memcpy(&stDevInfo, stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO));

    Qly::CameraHikVision * camera = new Qly::CameraHikVision(parent);
    if(camera->open(stDevInfo))
    {
        return camera;
    }
    return nullptr;
}
} //namespace Qly
